#include <gtest/gtest.h>
#include "Executor.hpp"
#include "PoseEq.hpp"

namespace adas
{
// 测试化用例14：F状态向东走2步
TEST(ExecutorTest, should_return_x_plus_2_given_status_is_fast_command_is_M_and_facing_is_E)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'E'}, CarsType::CAR));

    // when
    executor->Execute("FM");

    // then
    const Pose target({2, 0, 'E'});
    ASSERT_EQ(target, executor->Query());
}
// 测试化用例15：F状态向西走2步
TEST(ExecutorTest, should_return_x_minus_2_given_status_is_fast_command_is_M_and_facing_is_W)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'W'}, CarsType::CAR));
    // when
    executor->Execute("FM");
    // then
    const Pose target({-2, 0, 'W'});
    ASSERT_EQ(target, executor->Query());
}
// 测试化用例16：F状态向北走2步
TEST(ExecutorTest, should_return_y_plus_2_given_status_is_fast_command_is_M_and_facing_is_N)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'N'}, CarsType::CAR));
    // when
    executor->Execute("FM");
    // then
    const Pose target({0, 2, 'N'});
    ASSERT_EQ(target, executor->Query());
}
// 测试化用例17：F状态向南走2步
TEST(ExecutorTest, should_return_y_minus_2_given_status_is_fast_command_is_M_and_facing_is_S)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'S'}, CarsType::CAR));
    // when
    executor->Execute("FM");
    // then
    const Pose target({0, -2, 'S'});
    ASSERT_EQ(target, executor->Query());
}
// 测试化用例18：F状态向东一步左转为北
TEST(ExecutorTest, should_return_N_and_x_plus_1_given_status_is_fast_command_is_L_and_facing_is_E)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'E'}, CarsType::CAR));
    // when
    executor->Execute("FL");

    // then
    const Pose target({1, 0, 'N'});
    ASSERT_EQ(target, executor->Query());
}
// 测试化用例19：F状态向西一步左转为南
TEST(ExecutorTest, should_return_S_and_x_minus_1_given_status_is_fast_command_is_L_and_facing_is_W)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'W'}, CarsType::CAR));

    // when
    executor->Execute("FL");

    // then
    const Pose target({-1, 0, 'S'});
    ASSERT_EQ(target, executor->Query());
}
// 测试化用例20：F状态向北一步左转为西
TEST(ExecutorTest, should_return_W_and_y_plus_1_given_status_is_fast_command_is_L_and_facing_is_N)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'N'}, CarsType::CAR));

    // when
    executor->Execute("FL");

    // then
    const Pose target({0, 1, 'W'});
    ASSERT_EQ(target, executor->Query());
}
// 测试化用例21：F状态向南一步左转为东
TEST(ExecutorTest, should_return_E_and_y_minus_1_given_status_is_fast_command_is_L_and_facing_is_S)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'S'}, CarsType::CAR));

    // when
    executor->Execute("FL");

    // then
    const Pose target({0, -1, 'E'});
    ASSERT_EQ(target, executor->Query());
}
// 测试化用例22：F状态向东一步右转为南
TEST(ExecutorTest, should_return_S_and_x_plus_1_given_status_is_fast_command_is_R_and_facing_is_E)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'E'}, CarsType::CAR));

    // when
    executor->Execute("FR");

    // then
    const Pose target({1, 0, 'S'});
    ASSERT_EQ(target, executor->Query());
}

// 测试化用例23：F状态向西一步右转为北
TEST(ExecutorTest, should_return_N_and_x_minus_1_given_status_is_fast_command_is_R_and_facing_is_W)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'W'}, CarsType::CAR));

    // when
    executor->Execute("FR");

    // then
    const Pose target({-1, 0, 'N'});
    ASSERT_EQ(target, executor->Query());
}
// 测试化用例24：F状态向北一步右转为东
TEST(ExecutorTest, should_return_E_and_y_plus_1_given_status_is_fast_command_is_R_and_facing_is_N)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'N'}, CarsType::CAR));

    // when
    executor->Execute("FR");

    // then
    const Pose target({0, 1, 'E'});
    ASSERT_EQ(target, executor->Query());
}
// 测试化用例25：F状态向南一步右转为西
TEST(ExecutorTest, should_return_W_and_y_minus_1_given_status_is_fast_command_is_R_and_facing_is_S)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'S'}, CarsType::CAR));
    // when
    executor->Execute("FR");
    // then
    const Pose target({0, -1, 'W'});
    ASSERT_EQ(target, executor->Query());
}
// 测试化用例26：FF状态向东走1步取消状态
TEST(ExecutorTest, should_return_y_plus_1_given_command_is_FFM_and_facing_is_N)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'N'}, CarsType::CAR));

    // when
    executor->Execute("FFM");

    // then
    const Pose target({0, 1, 'N'});
    ASSERT_EQ(target, executor->Query());
}
// 测试化用例27：FF状态向西走1步取消状态
TEST(ExecutorTest, should_return_y_minus_1_given_command_is_FFM_and_facing_is_S)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'S'}, CarsType::CAR));

    // when
    executor->Execute("FFM");

    // then
    const Pose target({0, -1, 'S'});
}
// 测试化用例28：FF状态向北走1步取消状态
TEST(ExecutorTest, should_return_x_plus_1_given_command_is_FFM_and_facing_is_E)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'E'}, CarsType::CAR));

    // when
    executor->Execute("FFM");

    // then
    const Pose target({1, 0, 'E'});
}
// 测试化用例29：FF状态向南走1步取消状态
TEST(ExecutorTest, should_return_x_minus_1_given_command_is_FFM_and_facing_is_W)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'W'}, CarsType::CAR));

    // when
    executor->Execute("FFM");

    // then
    const Pose target({-1, 0, 'W'});
}

}